using System;
using NFreeMarker.Template;

namespace NFreeMarker.Core
{
    /**
     * A class that represents a Range between two integers.
     * inclusive of the end-points. It can be ascending or
     * descending. 
     * @author <a href="mailto:jon@revusky.com">Jonathan Revusky</a>
     */

    internal class NumericalRange : ITemplateSequenceModel //, java.io.Serializable
    {
        private readonly int _lower;
        private readonly int _upper;
        private readonly bool _descending;
        private readonly bool _norhs; // if norhs is true, then we have a half-range, like n..

        /**
         * Constructor for half-range, i.e. n..
         */

        public NumericalRange(int lower)
        {
            _norhs = true;
            _lower = lower;
        }

        public NumericalRange(int left, int right)
        {
            _lower = Math.Min(left, right);
            _upper = Math.Max(left, right);
            _descending = (left != _lower);
        }

        public ITemplateModel Get(int i)
        {
            int index = _descending ? (_upper - i) : (_lower + i);
            if ((_norhs && index > _upper) || index < _lower)
            {
                throw new TemplateModelException("out of bounds of range");
            }
            return new SimpleNumber(index);
        }

        public int Size()
        {
            return 1 + _upper - _lower;
        }

        private bool HasRhs()
        {
            return !_norhs;
        }
    }
}